#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <cerrno>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <functional>
#include <signal.h>
#include "logMessage.hpp"
#include <fcntl.h>
#define gport 8080
#define gbacklog 32
class Sock
{
public:
    // 创建套接字
    static int Socket()
    {
        int socketfd = socket(AF_INET, SOCK_STREAM, 0);
        if (socketfd < 0)
        {
            logMessage(ERROR, "socket create error errno : %d", errno);
            exit(2);
        }
        logMessage(NORMAL, "socket success");
        // 设置地址复用
        int opt = 1;
        setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof opt);
        return socketfd;
    }
    // bind
    static void Bind(int socketfd, int port)
    {
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(port);
        local.sin_addr.s_addr = INADDR_ANY;
        if (bind(socketfd, (struct sockaddr *)&local, sizeof(local)) < 0)
        {
            logMessage(ERROR, "bind error  errno : %d", errno);
            cerr << strerror(errno) << endl;
            exit(2);
        }
        logMessage(NORMAL, "bind success");
    }
    // listen
    static void Listen(int socketfd)
    {
        int listenfd = listen(socketfd, gbacklog);
        if (listenfd < 0)
        {
            logMessage(ERROR, "listen error errno : %d", errno);
            exit(2);
        }
        logMessage(NORMAL, "listen success");
    }
    // accept
    static int Accept(int socketfd,string *client_ip,uint16_t *client_port)
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int sock = accept(socketfd, (struct sockaddr *)&peer, &len);
        if (sock < 0)
        {
            logMessage(ERROR, "accept error  errno : %d", errno);
            exit(2);
        }
        //从peer中提取出客户端的端口号和ip
        *client_ip = inet_ntoa(peer.sin_addr);
        *client_port = ntohs(peer.sin_port);
        return sock;

    }
};
